#ifndef AIKIT_TEST
#define AIKIT_TEST

#include "tool/tool.h"
#include "server/server.h"

#include <fstream>
#include <assert.h>
#include <cstring>
#include <atomic>
#include <unistd.h>

#include "aikit_biz_api.h"
#include "aikit_constant.h"
#include "aikit_biz_config.h"

using namespace AIKIT;

static std::atomic_bool ttsFinished(false);

FILE *fin = nullptr;
static const char *ABILITY = "e2e44feff";

std::mutex buffer_mutex;
std::vector<uint8_t> AudioBuffer;

void OnOutput(AIKIT_HANDLE* handle, const AIKIT_OutputData* output){
    //printf("OnOutput key:%s\n",(char*)output->node->key);
    //printf("OnOutput status:%d\n",output->node->status);
    if((output->node->value) && (fin != nullptr))
    if(output->node->value)
    {
        //fwrite(output->node->value, sizeof(char), output->node->len, fin);
        // Head head;
        // head.Len = output->node->len;
        // send(server::thisTask.fd, &head, sizeof(head), 0);
        // server::Server->sendMessage(reinterpret_cast<char*>(output->node->value), server::thisTask.fd, output->node->len);

        std::lock_guard<std::mutex> lock(buffer_mutex);
        uint8_t* Buffer = static_cast<uint8_t*>(output->node->value);
        AudioBuffer.insert(AudioBuffer.end(), Buffer, Buffer + output->node->len);
    }
}

void OnEvent(AIKIT_HANDLE* handle, AIKIT_EVENT eventType, const AIKIT_OutputEvent* eventValue){
    printf("OnEvent:%d\n",eventType);
    if(eventType == AIKIT_Event_End){
        ttsFinished = true;

        Head head;
        head.Len = AudioBuffer.size();
        if (send(server::thisTask.fd, &head, sizeof(head), 0) <= 0)
        {
            std::cerr << "send AudioBuffer head failed" << std::endl;
        }
        if (!server::Server->sendMessage(AudioBuffer.data(), server::thisTask.fd, AudioBuffer.size()))
        {
            std::cerr << "send AudioBuffer failed" << std::endl;
        }
        AudioBuffer.clear();

        // std::string end = "_END_";
        // Head head;
        // head.Len = end.size();
        // send(server::thisTask.fd, &head, sizeof(head), 0);
        // server::Server->sendMessage(reinterpret_cast<char*>(&end), server::thisTask.fd, end.size());
    }
}

void OnError(AIKIT_HANDLE* handle, int32_t err, const char* desc){
    printf("OnError:%d\n",err);
}

void TestXTTS(std::string cntext, int32_t& fileSize, std::string FileName){
    std::string cmd;
    std::string pcmFile = FileName + ".pcm";
    std::string wavFile = FileName + ".wav";
    AIKIT_ParamBuilder* paramBuilder = nullptr;
    AIKIT_DataBuilder* dataBuilder = nullptr;   
    std::string entext = "hello everyone, this is catherine speeking";
    //std::string cntext = "今天天气很好，很适合出去玩。";
    AIKIT_HANDLE* handle = nullptr;
    AiText* aiText_raw = nullptr;
    ttsFinished = false;
    const char *role = "xiaoyan";
    //const char *role = "catherine"; 
    paramBuilder = AIKIT_ParamBuilder::create();
    paramBuilder->clear();
    paramBuilder->param("vcn", role, strlen(role));//必选参数，60020：xiaoyan发音人60030：xiaofeng发音人69010：john英文发音人69020：catherine英文发音人
    paramBuilder->param("vcnModel", role, strlen(role));//必选参数，取值与vcn保持一致
    paramBuilder->param("language",1);//必须参数，1是中文，2是英文，是英文时，对应文本也得是英文
    //paramBuilder->param("speed",100); //可选参数，默认为0
    //paramBuilder->param("pitch",100); //可选参数，默认为0
    //paramBuilder->param("volume",100);//可选参数，默认为0
    paramBuilder->param("textEncoding","UTF-8", strlen("UTF-8")); //可选参数，文本编码格式，默认为65001，UTF8格式
    int ret = AIKIT_Start(ABILITY,AIKIT_Builder::build(paramBuilder),nullptr,&handle);
    printf("AIKIT_Start:%d\n",ret);
    if(ret != 0){
        goto exit;
    }
    dataBuilder = AIKIT_DataBuilder::create();
    dataBuilder->clear();
    aiText_raw = AiText::get("text")->data(cntext.c_str(),cntext.length())->once()->valid();
    dataBuilder->payload(aiText_raw);


    fin = fopen(pcmFile.c_str(), "wb");
    if (fin == nullptr) {
        printf("fopen output.pcm fail.\n");
        goto exit;
    }
    ret = AIKIT_Write(handle,AIKIT_Builder::build(dataBuilder));
    printf("AIKIT_Write:%d\n",ret);
    if(ret != 0){
        fclose(fin);
        goto exit;
    }

    while(ttsFinished != true){
        usleep(1000);
    }

    fileSize = tool::getFileSize(pcmFile.c_str());
    ret = AIKIT_End(handle);

    exit:
        if (fin != nullptr) {
            fclose(fin);
            fin = nullptr;
        }   
        if(paramBuilder != nullptr){
            delete paramBuilder;
            paramBuilder = nullptr;
        }

        if(dataBuilder != nullptr){
            delete dataBuilder;
            dataBuilder = nullptr;
        }
        
}

void XTTS_Stream(std::string cntext) {
    AIKIT_ParamBuilder* paramBuilder = nullptr;
    AIKIT_DataBuilder* dataBuilder = nullptr;   
    AIKIT_HANDLE* handle = nullptr;
    AiText* aiText_raw = nullptr;
    ttsFinished = false;
    const char *role = "xiaoyan";
    //const char *role = "catherine"; 
    paramBuilder = AIKIT_ParamBuilder::create();
    paramBuilder->clear();
    paramBuilder->param("vcn", role, strlen(role));//必选参数，60020：xiaoyan发音人60030：xiaofeng发音人69010：john英文发音人69020：catherine英文发音人
    paramBuilder->param("vcnModel", role, strlen(role));//必选参数，取值与vcn保持一致
    paramBuilder->param("language",1);//必须参数，1是中文，2是英文，是英文时，对应文本也得是英文
    //paramBuilder->param("speed",100); //可选参数，默认为0
    //paramBuilder->param("pitch",100); //可选参数，默认为0
    //paramBuilder->param("volume",100);//可选参数，默认为0
    paramBuilder->param("textEncoding","UTF-8", strlen("UTF-8")); //可选参数，文本编码格式，默认为65001，UTF8格式
    int ret = AIKIT_Start(ABILITY,AIKIT_Builder::build(paramBuilder),nullptr,&handle);
    printf("AIKIT_Start:%d\n",ret);
    if(ret != 0){
        goto exit;
    }
    dataBuilder = AIKIT_DataBuilder::create();
    dataBuilder->clear();
    aiText_raw = AiText::get("text")->data(cntext.c_str(),cntext.length())->once()->valid();
    dataBuilder->payload(aiText_raw);



    fin = fopen("./output.pcm", "wb");
    if (fin == nullptr) {
        printf("fopen output.pcm fail.\n");
        goto exit;
    }
    ret = AIKIT_Write(handle,AIKIT_Builder::build(dataBuilder));
    printf("AIKIT_Write:%d\n",ret);
    if(ret != 0){
        fclose(fin);
        goto exit;
    }

    while(ttsFinished != true){
        usleep(1000);
    }
    
    ret = AIKIT_End(handle);

    exit:
        if (fin != nullptr) {
            fclose(fin);
            fin = nullptr;
        }   
        if(paramBuilder != nullptr){
            delete paramBuilder;
            paramBuilder = nullptr;
        }

        if(dataBuilder != nullptr){
            delete dataBuilder;
            dataBuilder = nullptr;
        }
}

void AEE_Init(){
    AIKIT_Configurator::builder()
        .app()
			.appID("249e3d13")
            .apiSecret("MDNiYzUwNzZkOTc3NGJiZGNkNWE3NDhk")
			.apiKey("32665f524a5b48a12f347fb4901a8110")
			.workDir("../workDir")
		.auth()
			.authType(0)
		.log()
			.logLevel(LOG_LVL_INFO)
			.logPath("../");
    int ret = AIKIT_Init();
    if(ret != 0){
        printf("AIKIT_Init failed:%d\n",ret);
        return;
    }
    AIKIT_Callbacks cbs = {OnOutput,OnEvent,OnError};
    AIKIT_RegisterAbilityCallback(ABILITY,cbs);
    // AIKIT_RegisterCallback(cbs);            
}

#endif